package com.icez.baseutil

import android.animation.ValueAnimator.AnimatorUpdateListener
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import java.util.*


/**
 * Created by Fussen on 2017/4/21.
 *
 *
 * 不可滚动的条形图
 */
class BarChart @JvmOverloads constructor(
    context: Context?,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) :
    View(context, attrs, defStyleAttr) {
    private var mChartPaint: Paint? = null
    private var mBound: Rect? = null
    private var textStart = 0f
    private var mHeight = 0
    private var mWidth = 0
    private var verticalList: List<Float> = ArrayList()
    private var horizontalList: List<String> = ArrayList()
    private val verticalWidth = 100f
    private var chartWidth //表的总宽度，除过外间距
            = 0f
    private val outSpace = verticalWidth // 柱子与纵轴的距离
    private var startChart = verticalWidth //柱子开始的横坐标
    private var interval //柱子之间的间隔
            = 0f
    private val bottomHeight = 100f //底部横坐标高度
    private var barWidth //柱子的真实宽度
            = 0f
    private var preBarWidth = 0f
    private var maxValue = "2" //默认最大值
    private var middleValue = "1"
    private val mPaddingTop = 20
    private val chartHeight = 10 //默认柱子高度
    private var noDataPaint: Paint? = null
    private var textXpaint: Paint? = null
    private var linePaint: Paint? = null
    private val noDataColor = "#66FF6933"
    private val textColor = "#FFBEBEBE"
    private val lineColor = "#E4E5E6"
    private val chartColor = "#FF6933"
    private val mDuriation = 3000
    private var isShort = true
    private var allInteval = 0f
    private var allBarwidth = 0f
    private val barPercent = 0.1f
    private val intevalPercent = 0.04f //间隔占总表格的比例 100%是1
    private var allChartWidth //表格的柱子和间隔的总宽
            = 0f
    private var textYpaint: Paint? = null
    private var mAnimator: ChartAnimator? = null
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        //宽度的模式
        val mWidthModle = MeasureSpec.getMode(widthMeasureSpec)
        //宽度大小
        val mWidthSize = MeasureSpec.getSize(widthMeasureSpec)
        val mHeightModle = MeasureSpec.getMode(heightMeasureSpec)
        val mHeightSize = MeasureSpec.getSize(heightMeasureSpec)
        //如果明确大小,直接设置大小
        if (mWidthModle == MeasureSpec.EXACTLY) {
            mWidth = mWidthSize
        } else {
            //计算宽度,可以根据实际情况进行计算
            mWidth = paddingLeft + paddingRight
            //如果为AT_MOST, 不允许超过默认宽度的大小
            if (mWidthModle == MeasureSpec.AT_MOST) {
                mWidth = Math.min(mWidth, mWidthSize)
            }
        }
        if (mHeightModle == MeasureSpec.EXACTLY) {
            mHeight = mHeightSize
        } else {
            mHeight = paddingTop + paddingBottom
            if (mHeightModle == MeasureSpec.AT_MOST) {
                mHeight = Math.min(mHeight, mHeightSize)
            }
        }
        //设置测量完成的宽高
        setMeasuredDimension(mWidth, mHeight)
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        mWidth = width
        mHeight = height - mPaddingTop
        chartWidth = mWidth - outSpace
        if (isShort) {
            //每个柱子宽度
            barWidth = (chartWidth * barPercent)
            interval = (chartWidth * intevalPercent)
            //所有柱子宽度 之和
            allBarwidth = horizontalList.size * barWidth
            //所有间隔宽 之和
            allInteval = (horizontalList.size - 1) * interval

            //所有柱子和间隔的宽度
            allChartWidth = allBarwidth + allInteval

            //柱子开始的横坐标
            startChart = outSpace + (chartWidth / 2f - allChartWidth / 2f)
        } else {
            //每个柱子的宽度 没有间隔
            try {
                preBarWidth = chartWidth / verticalList.size
            } catch (e: Exception) {
            }

            //柱子之间的间隔 为没有间隔柱子的宽度的30%
            interval = preBarWidth / 10f * 3f
            barWidth = preBarWidth - interval
            startChart = verticalWidth
        }

        //////////////////////////////////////////

        //横坐标
        textStart = startChart + barWidth / 2f
    }

    private fun init() {

        //初始化动画
        mAnimator = ChartAnimator(AnimatorUpdateListener {
            postInvalidate()
        })
        mBound = Rect()


        //柱子画笔
        mChartPaint = Paint()
        mChartPaint!!.isAntiAlias = true
        mChartPaint!!.color = Color.parseColor(chartColor)


        //线画笔
        linePaint = Paint()
        linePaint!!.isAntiAlias = true
        linePaint!!.color = Color.parseColor(lineColor)

        //x纵坐标 画笔
        textXpaint = Paint()
        textXpaint!!.isAntiAlias = true
        textXpaint!!.textSize = 27f
        textXpaint!!.textAlign = Paint.Align.CENTER
        textXpaint!!.color = Color.parseColor(textColor)

        //Y纵坐标 画笔
        textYpaint = Paint()
        textYpaint!!.isAntiAlias = true
        textYpaint!!.textSize = 28f
        textYpaint!!.textAlign = Paint.Align.LEFT
        textYpaint!!.color = Color.parseColor(textColor)

        //无数据时的画笔
        noDataPaint = Paint()
        noDataPaint!!.isAntiAlias = true
        noDataPaint!!.color = Color.parseColor(noDataColor)
        noDataPaint!!.style = Paint.Style.FILL
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val lineInterval = (mHeight - bottomHeight) / 4f //横线之间的间距  纵向
        val textHeight = mHeight + mPaddingTop - bottomHeight //横坐标高度

        //画线
        drawLine(canvas, lineInterval, textHeight)

        //画纵坐标
        drawYtext(canvas, lineInterval, textHeight)

        //画横坐标
        val textTempStart = textStart
        drawXtext(canvas, textTempStart)
        val chartTempStart = startChart
        val size = (mHeight - bottomHeight) / 100f //比例

        //画柱子
        drawBar(canvas, chartTempStart, size)
    }

    /**
     * 画柱子
     *
     * @param canvas
     * @param chartTempStart
     * @param size
     */
    private fun drawBar(canvas: Canvas, chartTempStart: Float, size: Float) {
        var chartTempStart = chartTempStart
        if (isShort) {
            for (i in verticalList.indices) {
                //每个数据点所占的Y轴高度
                val barHeight = verticalList[i] / java.lang.Float.valueOf(maxValue) * 100f * size
                val realBarHeight: Float = barHeight * (mAnimator?.phaseY ?: 0f)
                if (verticalList[0] == 0f) {
                    canvas.drawRect(
                        chartTempStart,
                        mHeight - bottomHeight + mPaddingTop - chartHeight,
                        chartTempStart + barWidth,
                        mHeight + mPaddingTop - bottomHeight,
                        noDataPaint!!
                    )
                } else {
                    canvas.drawRect(
                        chartTempStart,
                        mHeight - bottomHeight + mPaddingTop - realBarHeight,
                        chartTempStart + barWidth,
                        mHeight + mPaddingTop - bottomHeight,
                        mChartPaint!!
                    )
                }
                chartTempStart += barWidth + interval
            }
        } else {
            for (i in verticalList.indices) {

                //每个数据点所占的Y轴高度
                val barHeight = verticalList[i] / java.lang.Float.valueOf(maxValue) * 100f * size
                val realBarHeight: Float = barHeight * (mAnimator?.phaseY ?: 0f)

                //画柱状图 矩形
                val rectF = RectF()
                rectF.left = chartTempStart
                rectF.right = chartTempStart + barWidth
                rectF.bottom = mHeight + mPaddingTop - bottomHeight
                if (verticalList[i] == 0f) { //如果纵轴为0情况处理
                    rectF.top = mHeight - bottomHeight + mPaddingTop - chartHeight
                    canvas.drawRect(rectF, noDataPaint!!)
                } else {
                    rectF.top = mHeight - bottomHeight + mPaddingTop - realBarHeight
                    canvas.drawRect(rectF, mChartPaint!!)
                }
                chartTempStart += preBarWidth
            }
        }
    }

    /**
     * 画x轴
     *
     * @param canvas
     * @param textTempStart
     */
    private fun drawXtext(canvas: Canvas, textTempStart: Float) {
        var textTempStart = textTempStart
        if (isShort) {
            for (i in verticalList.indices) {
                textXpaint!!.getTextBounds(horizontalList[i], 0, horizontalList[i].length, mBound)
                val fontMetrics = textXpaint!!.fontMetricsInt
                val baseline =
                    (mHeight + mPaddingTop - bottomHeight + ((bottomHeight - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top)).toInt()
                canvas.drawText(
                    horizontalList[i], textTempStart, baseline.toFloat(),
                    textXpaint!!
                )
                //                canvas.drawLine(textTempStart, mHeight + mPaddingTop - bottomHeight, textTempStart, 0, linePaint);
                textTempStart += barWidth + interval
            }
        } else {
            if (horizontalList.size < 13) {
                for (i in horizontalList.indices) {

//                canvas.drawLine(textTempStart, mHeight + mPaddingTop - bottomHeight, textTempStart, 0, linePaint);


                    //画横轴
                    textXpaint!!.getTextBounds(
                        horizontalList[i],
                        0,
                        horizontalList[i].length,
                        mBound
                    )
                    val fontMetrics = textXpaint!!.fontMetricsInt
                    val baseline =
                        (mHeight + mPaddingTop - bottomHeight + ((bottomHeight - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top)).toInt()
                    canvas.drawText(
                        horizontalList[i], textTempStart, baseline.toFloat(),
                        textXpaint!!
                    )
                    textTempStart += preBarWidth
                }
            } else {
                for (i in horizontalList.indices) {
                    if (i % 4 == 0) {
                        //画横轴
                        textXpaint!!.getTextBounds(
                            horizontalList[i],
                            0,
                            horizontalList[i].length,
                            mBound
                        )
                        val fontMetrics = textXpaint!!.fontMetricsInt
                        val baseline =
                            (mHeight + mPaddingTop - bottomHeight + ((bottomHeight - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top)).toInt()
                        canvas.drawText(
                            horizontalList[i], textTempStart, baseline.toFloat(),
                            textXpaint!!
                        )
                    }
                    textTempStart += preBarWidth
                }
            }
        }
    }

    /**
     * 画Y轴
     *
     * @param canvas
     * @param lineInterval
     * @param textHeight
     */
    private fun drawYtext(canvas: Canvas, lineInterval: Float, textHeight: Float) {
        canvas.drawText("0", 0f, textHeight, textYpaint!!)
        canvas.drawText(middleValue, 0f, textHeight - lineInterval * 2f + 10f, textYpaint!!)
        canvas.drawText(maxValue, 0f, textHeight - lineInterval * 4f + 10f, textYpaint!!)
    }

    /**
     * 画线
     *
     * @param canvas
     * @param lineInterval
     * @param textHeight
     */
    private fun drawLine(canvas: Canvas, lineInterval: Float, textHeight: Float) {
        canvas.drawLine(outSpace - 10f, textHeight, mWidth.toFloat(), textHeight, linePaint!!)
        canvas.drawLine(
            outSpace - 10f, textHeight - lineInterval, mWidth.toFloat(), textHeight - lineInterval,
            linePaint!!
        )
        canvas.drawLine(
            outSpace - 10f,
            textHeight - lineInterval * 2f,
            mWidth.toFloat(),
            textHeight - lineInterval * 2f,
            linePaint!!
        )
        canvas.drawLine(
            outSpace - 10f,
            textHeight - lineInterval * 3f,
            mWidth.toFloat(),
            textHeight - lineInterval * 3f,
            linePaint!!
        )
        canvas.drawLine(
            outSpace - 10f,
            textHeight - lineInterval * 4f,
            mWidth.toFloat(),
            textHeight - lineInterval * 4f,
            linePaint!!
        )
    }

    /**
     * 重新指定起始位置
     *
     * @param verticalList
     */
    private fun measureWidthShort(verticalList: List<Float>) {
        isShort = true
        //每个柱子宽度
        barWidth = (chartWidth * barPercent)
        interval = (chartWidth * intevalPercent)


        //所有柱子宽度 之和
        allBarwidth = verticalList.size * barWidth
        //所有间隔宽 之和
        allInteval = (verticalList.size - 1) * interval

        //所有柱子和间隔的宽度
        allChartWidth = allBarwidth + allInteval

        //柱子开始的横坐标
        startChart = outSpace + (chartWidth / 2f - allChartWidth / 2f)
        textStart = startChart + barWidth / 2f
    }

    /**
     * 重新指定起始位置
     *
     * @param verticalList
     */
    private fun measureWidth(verticalList: List<Float>) {
        isShort = false
        //每个柱子的宽度 没有间隔
        try {
            preBarWidth = chartWidth / verticalList.size
        } catch (e: Exception) {
        }
        //柱子之间的间隔 为没有间隔柱子的宽度的30%
        interval = preBarWidth / 10f * 3f
        barWidth = preBarWidth - interval
        startChart = verticalWidth
        textStart = startChart + barWidth / 2f
    }

    /**
     * 设置纵轴数据
     *
     * @param verticalList
     */
    fun setVerticalList(verticalList: List<Float>?) {
        if (verticalList != null) {
            this.verticalList = verticalList
        } else {
            maxValue = "2"
            middleValue = "1"
            invalidate()
            return
        }
        if (verticalList.size <= 6) {
            measureWidthShort(verticalList)
            if (Collections.max(verticalList) > 2) {
                var tempMax = Math.round(Collections.max(verticalList))
                while (tempMax % 10 != 0) {
                    tempMax++
                }
                val middle = tempMax / 2
                maxValue = tempMax.toString()
                middleValue = middle.toString()
            } else {
                maxValue = "2"
                middleValue = "1"
            }
        } else {
            measureWidth(verticalList)
            if (Collections.max(verticalList) > 2) {
                var tempMax = Math.round(Collections.max(verticalList))
                while (tempMax % 10 != 0) {
                    tempMax++
                }
                val middle = tempMax / 2
                maxValue = tempMax.toString()
                middleValue = middle.toString()
            } else {
                maxValue = "2"
                middleValue = "1"
            }
        }
        mAnimator?.animateY(mDuriation)
    }

    /**
     * 设置横轴数据
     *
     * @param horizontalList
     */
    fun setHorizontalList(horizontalList: List<String>?) {
        if (horizontalList != null) this.horizontalList = horizontalList
    }

    companion object {
        private const val TAG = "BarChart"
    }

    init {
        init()
    }
}